import datetime
import json

import aiomysql
from fastapi import APIRouter, Request
from pymysql.converters import escape_string

from apps.core.m_route import ContextIncludedRoute
from apps.core.return_info import SUCCESS, ReturnInfo, FAILED
from apps.crawler_platform.core_api.models import UpdateTaskModel
from apps.crawler_platform.core_platform.core_sql import CoreSqlMixin
from apps.crawler_platform.core_platform.g_model import InputPlatformModel, TaskInfoSaveSettingModel, TaskInfoModel, \
    TaskInfoSaveSettingChangeModel

router = APIRouter(route_class=ContextIncludedRoute)


@router.post("/setting/save_task")
async def save_task(request: Request, input: InputPlatformModel[TaskInfoModel]):
    """
    保存任务至mysql及redis缓存
    :param input:
    :return:
    """
    return_info = ReturnInfo()
    data = input.data.dict()
    taskKey = "{}_{}_{}_{}".format(data["task_name"], data["task_tag"], data["groups"], data["order_num"])
    redis = request.app.state.redis
    data["redis_uptime"] = str(datetime.datetime.now())
    res_value = await redis.hset("taskinfo", taskKey, json.dumps(data, ensure_ascii=False))
    # res_value 值为0，redis已存在key覆盖成功，值为1redis不存在key创建保存成功
    if (res_value == 0) or (res_value == 1):
        await CoreSqlMixin.save_taskinfo(data)
        return_info.status = SUCCESS
        return_info.msg_code = 200
        return_info.msg = "保存到任务成功"
        return return_info.todict()
    else:
        return_info.status = FAILED
        return_info.msg_code = 400
        return_info.msg = "保存到任务失败"
        return return_info.todict()


@router.post("/setting/update_task")
async def update_task(request: Request, input: InputPlatformModel[UpdateTaskModel]):
    """
    更新任务至mysql及redis缓存
    :param input:#     :return:
    """
    return_info = ReturnInfo()
    data = input.data.dict()
    from main import app
    sql = f"select * from taskinfo where task_name='{data['basekey']['task_name']}' and task_tag='{data['basekey']['task_tag']}' and order_num={data['basekey']['order_num']} and `groups`='{data['basekey']['groups']}' "
    pool = app.state.pool
    async with pool.acquire() as conn:
        async with conn.cursor(aiomysql.DictCursor) as cur:
            await cur.execute(sql)
            row = await cur.fetchone()
    del row["create_time"]
    del row["update_time"]
    taskKey = "{}_{}_{}_{}".format(data['basekey']["task_name"],
                                   data['basekey']["task_tag"],
                                   data['basekey']["groups"],
                                   data['basekey']["order_num"])
    redis = request.app.state.redis
    for setinfo in data["upset"]:
        if setinfo['flag'] == 'ture':
            sql = f"update taskinfo set '{setinfo['key']}' = '{setinfo['value']}' where " \
                  f"task_name = '{data['basekey']['task_name']}' and task_tag = '{data['basekey']['task_tag']}' and order_num = {data['basekey']['order_num']} and groups = '{data['basekey']['groups']}'"
            row[setinfo['key']] = setinfo['value']
            row["redis_uptime"] = str(datetime.datetime.now())
            res_value = await redis.hset("taskinfo", taskKey, json.dumps(row, ensure_ascii=False))
            if (res_value == 0) or (res_value == 1):
                await CoreSqlMixin.update_taskinfo(sql)
                return_info.status = SUCCESS
                return_info.msg_code = 200
                return_info.msg = "保存到任务成功"
                return_info.data = ""
                return return_info.todict()
            else:
                return_info.status = FAILED
                return_info.msg_code = 400
                return_info.msg = "保存到任务失败"
                return_info.data = ""
                return return_info.todict()
        else:
            infodict = eval(row[setinfo['key']])
            infodict[setinfo['value']['key']] = setinfo['value']['value']
            row[setinfo['key']] = json.dumps(infodict, ensure_ascii=False)
            sql = f"update taskinfo set {setinfo['key']} = '{escape_string(str(infodict))}' where " \
                  f"task_name = '{data['basekey']['task_name']}' and task_tag = '{data['basekey']['task_tag']}' and order_num = {data['basekey']['order_num']} and `groups` = '{data['basekey']['groups']}'"
            row["redis_uptime"] = str(datetime.datetime.now())
            redis.hset("taskinfo", taskKey, json.dumps(row, ensure_ascii=False))
            res_value = await redis.hset("taskinfo", taskKey, json.dumps(row, ensure_ascii=False))
            if (res_value == 0) or (res_value == 1):
                await CoreSqlMixin.update_taskinfo(sql)
                return_info.status = SUCCESS
                return_info.msg_code = 200
                return_info.msg = "保存到任务成功"
                return_info.data = ""
                return return_info.todict()
            else:
                return_info.status = FAILED
                return_info.msg_code = 400
                return_info.msg = "保存到任务失败"
                return_info.data = ""
                return return_info.todict()


@router.post("/setting/save_taskinfo_setting")
async def save_taskinfo_setting(request: Request, input: InputPlatformModel[TaskInfoSaveSettingModel]):
    """
    保存任务配置表至mysql及redis缓存
    :param input:
    :return:
    """
    return_info = ReturnInfo()
    data = input.data.dict()
    taskKey = "{}_{}".format(data["task_name"], data["task_tag"])
    redis = request.app.state.redis
    data["redis_uptime"] = str(datetime.datetime.now())
    res_value = await redis.hset("taskinfo_save_setting", taskKey, json.dumps(data, ensure_ascii=False))
    if (res_value == 0) or (res_value == 1):
        await CoreSqlMixin.save_taskinfo_set(data)
        return_info.status = SUCCESS
        return_info.msg_code = 200
        return_info.msg = "保存到任务配置成功"
        return return_info.todict()
    else:
        return_info.status = FAILED
        return_info.msg_code = 400
        return_info.msg = "保存任务配置失败"
        return return_info.todict()


@router.post("/setting/change_save_taskinfo_setting")
async def save_taskinfo_setting(input: InputPlatformModel[TaskInfoSaveSettingChangeModel]):
    """
    根据输入参数进行控制下载任务
    ZCN
    :param input:\n
            task_name:任务名，一般一个网站一个任务名

            task_tag: 任务标签，一般一个步骤一个任务标签，比如期刊分为cnkijournallist，cnkiissue，cnkiarticle
                      当然也兼容一些特殊的情况，比如海外版,网络首发等

            database_table_name: 用作表示子任务所属表

            table_name: taskinfo_save_setting表中的table_name字段

            switch: 用于确定本次请求归属, 0: 表示本次请求输入的参数 为关闭参数(即将输入tag_state或task_state置为0,其余置为1)
                    1: 表示本次请求输入的参数 为开启参数(即将输入tag_state或task_state置为1, 其余置为0)

            is_task: 用于控制本次请求是否为整个任务控制, 0: 表示本次请求不是以task_state 为整体(即将task_state置为1, 其余不做操作);
                     1: 表示本次请求是控制整个任务是以task_state 为整体(即将task_state置为1, 其余置为0)
    :return:
    """

    return_info = ReturnInfo()
    task_name = input.data.task_name
    task_tag = input.data.task_tag
    switch = input.data.switch
    database_table_name = input.data.database_table_name
    table_name = input.data.table_name
    is_task = input.data.is_task
    if is_task == "0":
        # 这种情况下  无论如何也要保证task_state = 1 以免下面 的另一种情况对这边造成干扰
        if switch == "0":
            sql_up1 = f"update {database_table_name} set task_state = 1, tag_state = 1 where table_name = '{table_name}'"
            sql_up2 = f"update {database_table_name} set task_state = 1, tag_state = 0 where task_name = '{task_name}' and task_tag = '{task_tag}'"
        elif switch == "1":
            sql_up1 = f"update {database_table_name} set task_state = 1, tag_state = 0 where table_name = '{table_name}'"
            sql_up2 = f"update {database_table_name} set task_state = 1, tag_state = 1 where task_name = '{task_name}' and task_tag = '{task_tag}'"
        else:
            return_info.status = FAILED
            return_info.msg_code = 251
            return_info.msg = "更新taskinfo_save_setting的任务控制配置失败(switch参数错误,只能为0或1)"
            return_info.data = ""
            return return_info.todict()

    elif is_task == "1":
        if switch == "0":
            sql_up1 = f"update {database_table_name} set task_state = 1"
            sql_up2 = f"update {database_table_name} set task_state = 0, tag_state = 0where task_name = '{task_name}'"
        elif switch == "1":
            sql_up1 = f"update {database_table_name} set task_state = 0"
            sql_up2 = f"update {database_table_name} set task_state = 1, tag_state = 1 where task_name = '{task_name}'"
        else:
            return_info.status = FAILED
            return_info.msg_code = 251
            return_info.msg = "更新taskinfo_save_setting的任务控制配置失败(switch参数错误,只能为0或1)"
            return_info.data = ""
            return return_info.todict()
    else:
        return_info.status = FAILED
        return_info.msg_code = 251
        return_info.msg = "更新taskinfo_save_setting的任务控制配置失败(is_task参数错误,只能为0或1)"
        return_info.data = ""
        return return_info.todict()

    from main import app
    pool = app.state.pool
    async with pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute(sql_up1)
            await conn.commit()
    async with pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute(sql_up2)
            await conn.commit()
    return_info.status = SUCCESS
    return_info.msg_code = 200
    return_info.msg = "更新taskinfo_save_setting的任务控制配置成功"
    return_info.data = ""
    return return_info.todict()
